package com.test.mybatis.dao;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;

import java.sql.Statement;
import java.util.Properties;

/**
 * @author lzy
 * @version v1.0
 * Create DateTime: 2018/11/21 9:35
 * <p>
 * 完成插件签名：告诉MyBatis当前插件用来拦截哪个对象的哪个方法
 */
@Slf4j
@Intercepts({@Signature(type = StatementHandler.class, method = "parameterize", args = {Statement.class})})
public class MyFirstPlugin implements Interceptor {

    /**
     * intercept:拦截
     * 拦截目标对象的目标方法执行
     *
     * @param invocation
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        //动态的改变一下sql的运行参数，以前查询1号员工，实际从数据库查询3号员工
        log.info("拦截到的对象:{}", invocation.getTarget());
        Object target = invocation.getTarget();
        //拿到：StatementHandler --> ParameterHandler --> parameterObject
        //拿到target的元数据
        MetaObject metaObject = SystemMetaObject.forObject(target);
        Object value = metaObject.getValue("parameterHandler.parameterObject");
        log.info("sql语句用的参数是:{}", value);
        metaObject.setValue("parameterHandler.parameterObject", 11);

        log.info("MyFirstPlugin...intercept:{}", invocation.getMethod());
        //执行目标方法
        Object result = invocation.proceed();
        //返回执行后的结果
        return result;
    }

    /**
     * plugin：包装目标对象，为目标对象创建一个代理对象
     *
     * @param target
     * @return
     */
    @Override
    public Object plugin(Object target) {
        log.info("MyFirstPlugin...plugin将要包装的对象:{}", target);
        //可以借助Plugin的wrap方法来使用当前的Interceptor包装目标对象
        Object warp = Plugin.wrap(target, this);
        //返回为当前target创建动态代理
        return warp;
    }

    /**
     * setProperties：将插件注册时的property属性设置进来
     *
     * @param properties
     */
    @Override
    public void setProperties(Properties properties) {
        log.info("插件配置的信息:{}", properties);
    }
}
